
#include "OTA.h"

size_t FactoryInformationSize = 0;
volatile char device_id[10];
volatile FactoryInformationTypedef FactoryInformation = {0};
volatile DeviceAckTypedef ACK = {0};
volatile DataReceptionTypedef Data_Reception_param = {0};
volatile char uart2_dma_rx_buffer[DMA_RX_BUFFER_SIZE];
volatile char uart2_dma_tx_buffer[DMA_TX_BUFFER_SIZE];

volatile u32         Program_addr;

volatile uint8_t  OTA_END_FLAG = 0;
volatile u8 IS_Updating = 0;

#if defined(USE_4G_MODELS) || defined(USE_ESP32_C3)
static ML307R_MQTT_Config_Typedef MMC = {
        .server_addr = "1033818uz84px.vicp.fun",
        .port = 47345,
        .pubtopic = "CH32_OTA/device_send",
        .subtopic = "CH32_OTA/device_recv",
        .client_id = "CH32_OTA_Client",
        .user_name = "feiniao",
        .password = "3333",
        .qos = 1
};
#endif

void Dev_DMA_Send(void* data, uint16_t len);


static UART_Device_Typedef dev = {
        .UARTx = USART2,
        .port = GPIOA,
        .tx_pin = GPIO_Pin_2,
        .rx_pin = GPIO_Pin_3,
        .gpio_tx_pin_mode = GPIO_Mode_AF_PP,
        .gpio_rx_pin_mode = GPIO_Mode_IN_FLOATING,
        .BaudRate = 115200,
        .StopBits = USART_StopBits_1,
        .WordLength = USART_WordLength_8b,
        .Parity = USART_Parity_No,
        .HardwareFlowControl = USART_HardwareFlowControl_None,
        .Mode = USART_Mode_Tx | USART_Mode_Rx,
        .TX_DMAx_Channely = DMA1_Channel6,
        .RX_DMAx_Channely = DMA1_Channel7,
        .USART_DMAReq = USART_DMAReq_Tx | USART_DMAReq_Rx,

        .USART_IT = USART_IT_IDLE,

        .NVIC_IRQChannel = USART2_IRQn,
        .NVIC_IRQChannelCmd = ENABLE,
        .NVIC_IRQChannelPreemptionPriority = 1,
        .NVIC_IRQChannelSubPriority = 1,

        .RCC_APB1Periph = RCC_APB1Periph_USART2,
        .RCC_APB2Periph = RCC_APB2Periph_GPIOA,
        .RCC_APB1PeriphClockCmd = RCC_APB1PeriphClockCmd,
        .RCC_APB2PeriphClockCmd = RCC_APB2PeriphClockCmd,

        .Data_Send_Func = Dev_DMA_Send
};



static Device_DMA_Typedef dev_dma_tx = {
        .DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR),
        .DMA_MemoryBaseAddr = (u32)uart2_dma_tx_buffer,
        .DMA_DIR = DMA_DIR_PeripheralDST,
        .DMA_BufferSize = sizeof(uart2_dma_tx_buffer),
        .DMA_PeripheralInc = DMA_PeripheralInc_Disable,
        .DMA_MemoryInc = DMA_MemoryInc_Enable,
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
        .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
        .DMA_Mode = DMA_Mode_Normal,
        .DMA_Priority = DMA_Priority_Low,
        .DMA_M2M = DMA_M2M_Disable,

        .DMAx_Channely = DMA1_Channel7,

        .RCC_AHBPeriph = RCC_AHBPeriph_DMA1,
        .RCC_AHBPeriphClockCmd = RCC_AHBPeriphClockCmd,
        .DMAy_FLAG = DMA1_FLAG_TC7
};



static Device_DMA_Typedef dev_dma_rx = {
        .DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR),
        .DMA_MemoryBaseAddr = (u32)uart2_dma_rx_buffer,
        .DMA_DIR = DMA_DIR_PeripheralSRC,
        .DMA_BufferSize = sizeof(uart2_dma_rx_buffer),
        .DMA_PeripheralInc = DMA_PeripheralInc_Disable,
        .DMA_MemoryInc = DMA_MemoryInc_Enable,
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word,      // DMA_PeripheralDataSize_Byte
        .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
        .DMA_Mode = DMA_Mode_Normal,
        .DMA_Priority = DMA_Priority_Low,
        .DMA_M2M = DMA_M2M_Disable,

        .DMAx_Channely = DMA1_Channel6,

        .RCC_AHBPeriph = RCC_AHBPeriph_DMA1,
        .RCC_AHBPeriphClockCmd = RCC_AHBPeriphClockCmd,
};



void Dev_DMA_Send(void* data, uint16_t len)
{
    // ​​必须先等待上一次DMA传输完成，再关闭DMA通道​​
    while(DMA_GetFlagStatus(dev_dma_tx.DMAy_FLAG) == RESET); /* Wait until USART2 TX DMA1 Transfer Complete */
    // 关闭DMA通道
    DMA_Cmd(dev_dma_tx.DMAx_Channely, DISABLE);

    printf("\r\nUSART2_DMA_is_Sending\r\n");

    // 清掉uart2_dma_tx_buffer
    memset((void*)uart2_dma_tx_buffer, 0, DMA_TX_BUFFER_SIZE);
    // 复制数据到发送缓冲区
    len = (len > DMA_TX_BUFFER_SIZE) ? DMA_TX_BUFFER_SIZE : len;
    memcpy((void*)uart2_dma_tx_buffer, data, len);
    printf("send: %s\r\n", uart2_dma_tx_buffer);

    DMA_SetCurrDataCounter(dev_dma_tx.DMAx_Channely, len);
    DMA_Cmd(dev_dma_tx.DMAx_Channely, ENABLE);

//        // CH32上可以不要这个
//     // 使能USART2的DMA传输请求
//    USART_DMACmd(USART2, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
}




void SendData_To_CommunicationDev(void* data, uint16_t len) {
#ifdef USE_4G_MODELS
    static char cmd_buf[DMA_TX_BUFFER_SIZE + 1] = {0};
    snprintf(cmd_buf, sizeof(cmd_buf),
             "AT+MQTTPUB=0,\"%s\",%d,0,0,%d,\"%s\"\r\n",
             MMC.pubtopic, MMC.qos, (int)strlen((char*)data), (char*)data);
    dev.Data_Send_Func(cmd_buf, strlen(cmd_buf));
    Start_Timer(MaxWaitTime);

#elif USE_ESP32_C3
    dev.Data_Send_Func(data, len);
    Start_Timer(MaxWaitTime);

#elif USE_OTA_SOFT_WARE
    dev.Data_Send_Func(data, len);
    Start_Timer(MaxWaitTime);
#endif
}


void Communication_Init(void) {
    BSP_USART_Init(&dev);
    BSP_DMA_INIT(&dev_dma_rx);
    BSP_DMA_INIT(&dev_dma_tx);
#ifdef USE_4G_MODELS
    static char cmd[250] = {0};
    // 禁用缓存模式（直接透传）
    snprintf(cmd, sizeof(cmd), "AT+MQTTCFG=\"cached\",0,0\r\n");
    dev.Data_Send_Func((void*)cmd, strlen(cmd));
    Delay_Ms(500);
    // 设置文本模式（JSON为文本格式）
    snprintf(cmd, sizeof(cmd), "AT+MQTTCFG=\"encoding\",0,0,0\r\n");
    dev.Data_Send_Func((void*)cmd, strlen(cmd));
    Delay_Ms(500);

    snprintf(cmd, sizeof(cmd),
                            "AT+MQTTCONN=0,\"%s\",%d,\"%s\",\"%s\",\"%s\"\r\n",
                            MMC.server_addr, MMC.port, MMC.client_id, MMC.user_name, MMC.password);
    dev.Data_Send_Func((void*)cmd, strlen(cmd));
    Delay_Ms(3000);

    snprintf(cmd, sizeof(cmd),
                            "AT+MQTTSUB=0,\"%s\",%d\r\n",
                            MMC.subtopic, MMC.qos);
    dev.Data_Send_Func((void*)cmd, strlen(cmd));
    Delay_Ms(3000);

#elif USE_ESP32_C3

#elif USE_OTA_SOFT_WARE

#endif
}



size_t FactoryInformationUpdate(FactoryInformationTypedef info) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        return 0;
    }
    cJSON_AddStringToObject(root, "device_id", info.device_id);
    cJSON_AddStringToObject(root, "current_fw", info.current_fw);
    cJSON_AddNumberToObject(root, "fw_size", info.fw_size);

    char* FactoryInformation_ = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);
    printf("ready to write: %s\r\n", FactoryInformation_);
    size_t writenByte = strlen(FactoryInformation_);
    AT24CXX_Write(FactoryInformationBaseAddr, (u8*)FactoryInformation_, strlen(FactoryInformation_));
    printf("write OK\r\n");
    cJSON_free(FactoryInformation_);

    return writenByte;
}



void OTA_Init(void) {
    key_init();
    AT24CXX_Init();
    Communication_Init();

    static char FactoryInformation_Be_read[FactoryInformationMaxSize + 1] = {0};
    AT24CXX_Read(FactoryInformationBaseAddr, (u8*)FactoryInformation_Be_read, FactoryInformationMaxSize);
    printf("FactoryInformation: %s\r\n", FactoryInformation_Be_read);

    cJSON* root = cJSON_Parse(FactoryInformation_Be_read);
    if (root == NULL) {
        const char* error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            printf("JSON parse error before: %s\r\n", error_ptr);
        }
        return;
    }
    cJSON* device_id_js = cJSON_GetObjectItemCaseSensitive(root, "device_id");
    if (!cJSON_IsString(device_id_js)) {
        printf("device_id_js is not a string!\r\n");
        cJSON_Delete(root);
        return;
    }
    printf("device_id: %s\r\n", device_id_js->valuestring);
    memcpy((void*)device_id, device_id_js->valuestring, strlen(device_id_js->valuestring));
    device_id[sizeof(device_id) - 1] = '\0';
    cJSON_Delete(root);

    FactoryInformation.device_id = (char*)device_id; // 拿出设备id
    printf("FactoryInformation.device_id: %s\r\n", FactoryInformation.device_id);
}



void UpgradeRequestInformationToNo(void) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        return;
    }
    cJSON_AddStringToObject(root, "UpgradeNeed", "no");

    char* UpgradeNeedInfo = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);

    AT24CXX_Write(UpgradeRequestInformationAddr, (u8*)UpgradeNeedInfo, strlen(UpgradeNeedInfo));

    cJSON_free(UpgradeNeedInfo);

    u8 temp[50] = {0};

    AT24CXX_Read(UpgradeRequestInformationAddr, temp, 50);

    printf("UpgradeNeedInfo: %s\r\n", temp);
}



void UpgradeRequestInformationToYes(void) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        return;
    }
    cJSON_AddStringToObject(root, "UpgradeNeed", "yes");

    char* UpgradeNeedInfo = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);

    AT24CXX_Write(UpgradeRequestInformationAddr, (u8*)UpgradeNeedInfo, strlen(UpgradeNeedInfo));

    cJSON_free(UpgradeNeedInfo);

    u8 temp[50] = {0};

    AT24CXX_Read(UpgradeRequestInformationAddr, temp, 50);

    printf("UpgradeNeedInfo: %s\r\n", temp);
}



uint8_t Upgrade_Request_Need_Detect(void) {
    uint8_t result = 0;

    u8 buffer[UpgradeRequestInformationMaxSize + 1] = {0};

    AT24CXX_Read(UpgradeRequestInformationAddr, buffer, UpgradeRequestInformationMaxSize);

    char UpgradeRequestInformation[FactoryInformationMaxSize + 1] = {0};

    memcpy(UpgradeRequestInformation, buffer, UpgradeRequestInformationMaxSize);

    printf("UpgradeRequestInformation: %s\r\n", UpgradeRequestInformation);

    cJSON* root = cJSON_Parse(UpgradeRequestInformation);
    if (root == NULL) {
        const char* error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            printf("JSON parse error before: %s\r\n", error_ptr);
        }
        return result | cJSON_Parse_failed;
    }

    cJSON* UpGradeInfo = cJSON_GetObjectItemCaseSensitive(root, "UpgradeNeed");
    if (!cJSON_IsString(UpGradeInfo)) {
        printf("UpgradeNeed is not a string!\r\n");
        cJSON_Delete(root);
        return result | cJSON_GetObjectItem_failde;
    }

    int is_need = (strcmp(UpGradeInfo->valuestring, "yes") == 0);

    printf("UpgradeNeed: %s\r\n", UpGradeInfo->valuestring);
    cJSON_Delete(root);

    return result | ((is_need) ? UpgradeNeed : UpgradeNotNeed);
}



char* Read_current_fw(void) {
    // 从E2pROM读fw
    char FactoryInformation[FactoryInformationMaxSize + 1] = {0};
    AT24CXX_Read(FactoryInformationBaseAddr, FactoryInformation, FactoryInformationMaxSize);
    printf("FactoryInformation: %s\r\n", FactoryInformation);

    cJSON* FactoryInformation_root = cJSON_Parse(FactoryInformation);
    if (FactoryInformation_root == NULL) {
        const char* error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            printf("JSON parse error before: %s\r\n", error_ptr);
        }
        return 0;
    }

    cJSON* current_fw = cJSON_GetObjectItemCaseSensitive(FactoryInformation_root, "current_fw");
    if (!cJSON_IsString(current_fw)) {
        printf("current_fw is not a string!\r\n");
        cJSON_Delete(FactoryInformation_root);
        return 0;
    }
    printf("current_fw value: %s\r\n", current_fw->valuestring);

    char* current_fw_info = malloc(strlen(current_fw->valuestring) + 1);
    if (current_fw_info != NULL) {
        strcpy(current_fw_info, current_fw->valuestring);
    }
    cJSON_Delete(FactoryInformation_root);
    cJSON_Delete(current_fw);

    return current_fw_info;
}



char* BuildUpgradeRequestInfo(void) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        return 0;
    }

    cJSON_AddStringToObject(root, "type", "request");
    cJSON_AddStringToObject(root, "device_id", FactoryInformation.device_id);
    cJSON_AddStringToObject(root, "current_fw", (const char*)Read_current_fw());

    char* UpgradeRequestInfo = cJSON_PrintUnformatted(root);
    printf("%s\r\n", UpgradeRequestInfo);
    cJSON_Delete(root);

    return UpgradeRequestInfo;
}



void Send_UpgradeRequest(void) {
    char* r = BuildUpgradeRequestInfo();
    SendData_To_CommunicationDev((void*)r, strlen(r));
    cJSON_free(r);
}



uint8_t AppExists(void) {

    uint8_t result = 0;

    u8 buffer[FactoryInformationMaxSize + 1] = {0};

    AT24CXX_Read(FactoryInformationBaseAddr, buffer, FactoryInformationSize);

    char FactoryInformation[FactoryInformationMaxSize + 1] = {0};

    memcpy(FactoryInformation, buffer, FactoryInformationSize);

    printf("FactoryInformation: %s\r\n", FactoryInformation);


    cJSON* root = cJSON_Parse(FactoryInformation);
    if (root == NULL) {
        const char* error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            printf("JSON parse error before: %s\r\n", error_ptr);
        }
        return result | cJSON_Parse_failed;
    }


    cJSON* current_fw = cJSON_GetObjectItemCaseSensitive(root, "current_fw");
    if (!cJSON_IsString(current_fw)) {
        printf("current_fw is not a string!\r\n");
        cJSON_Delete(root);
        return result | cJSON_GetObjectItem_failde;
    }

    int is_none = (strcmp(current_fw->valuestring, "none") == 0);

    printf("current_fw value: %s\r\n", current_fw->valuestring);
    cJSON_Delete(root);

    return result | ((is_none) ? App_Not_Exists : App_Exists);
}



char* DeviceAckBuid(DeviceAckTypedef ack) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        printf("DeviceAckBuid faild\r\n");
    }
    cJSON_AddStringToObject(root, "type", "ack");
    cJSON_AddStringToObject(root, "device_id", ack.device_id);
    cJSON_AddStringToObject(root, "status", ack.status);
    cJSON_AddNumberToObject(root, "next_seq", ack.next_seq);
    cJSON_AddBoolToObject(root, "end_flag", ack.end_flag);

    char* s = cJSON_PrintUnformatted(root);
    printf("ack: %s\r\n", s);
    cJSON_Delete(root);
    return s;
}



void extract_json_simple(const char *input, char *output) {
    const char *start = strchr(input, '{'); // 查找第一个{

    if (start != NULL) {
        strcpy(output, start); // 复制从{开始的所有内容
    } else {
        output[0] = '\0'; // 没有找到{则返回空字符串
    }
}



void CommunicationDev_Data_Perse (void) {
    // 获取实际接收到的数据长度
    uint16_t received_len = DMA_RX_BUFFER_SIZE - DMA_GetCurrDataCounter(dev_dma_rx.DMAx_Channely);

    printf("\r\nUSART2 DMA RX (%d bytes)\r\n ", received_len);

    static char buffer[DMA_RX_BUFFER_SIZE + 1] = {0};
    size_t len = received_len < DMA_RX_BUFFER_SIZE ? received_len : DMA_RX_BUFFER_SIZE;
    memset(buffer, 0, DMA_RX_BUFFER_SIZE + 1);
    memcpy(buffer, (void*)uart2_dma_rx_buffer, len);
    buffer[DMA_RX_BUFFER_SIZE] = '\0';
    printf("recv: %s\r\n", buffer);
    static char fixed_buffer[DMA_RX_BUFFER_SIZE + 1] = {0};
#ifdef USE_4G_MODELS
    // 4G模块发送成功会回传发送的数据，导致错误解析，处理如下
    // 观察发现回传的消息格式：
//    +MQTTPUB: 0,21405,106
//
//    OK
//    +MQTTURC: "puback",0,21405,0
    // 两则消息或三则消息
    //+MQTTURC: "publish",0,31,"CH32_OTA/device_send",80,80,{"type":"request","device_id":"CH32_001","current_fw":"none","trigger":"button"}
    // 前面两条不会造成影响，关键是第三条有json数据，我们就检测是否有“CH32_OTA/device_send”
    // 这明显是我们的发布主题，怎么会收到发布主题的消息呢，很奇怪
    // 处理：检测到"CH32_OTA/device_send"， 也就是MMC.pubtopic, 就return
    if (strstr(buffer, MMC.pubtopic) != NULL) { // "\"CH32_OTA/device_send\""
            printf("Found subtopic, returning...\r\n");
            return;
        }
    // 但又要注意：
    // 模块消息返回格式:
//    +MQTTURC: "publish",0,0,"CH32_OTA/device_recv",14,14,{
//      "q": 1
//    }
    // 真正的json从“{”开始， 要做相应处理才能解析json
    extract_json_simple(buffer, fixed_buffer);
    if (fixed_buffer[0] == '\0') {
        printf("fixed_buffer faild\r\n");
        return;
    }
    printf("fixed_buffer: %s\r\n", fixed_buffer);
    /*
     *处理帧，有三种帧， start, data, end, 是服务器发送来的
     *start:
     *{
          "type": "start",
          "device_id": "DEVICE_123"     // 目标设备ID
          "version": "1.0.1",
          "file_size": 32768,       // 固件总大小
          "block_size": 256,       // 每帧数据块大小
        }
     */
#elif USE_ESP32_C3
    memcpy(fixed_buffer, buffer, DMA_RX_BUFFER_SIZE + 1);
#elif USE_OTA_SOFT_WARE
    memcpy(fixed_buffer, buffer, DMA_RX_BUFFER_SIZE + 1);
#endif
    // 使用cJSON解析帧
    cJSON* frame = cJSON_Parse(fixed_buffer);
    if (frame == NULL) {
        const char* error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            printf("JSON parse error before: %s\r\n", error_ptr);
        }
        return;
    }
    // 提取type
    cJSON* type = cJSON_GetObjectItemCaseSensitive(frame, "type");
    if (!cJSON_IsString(type)) {
        printf("type is not a string!\r\n");
        cJSON_Delete(frame);
        return;
    }

    // 处理三种情况
    // 1）起始帧
    if (strcmp(type->valuestring, "start") == 0) {
        // 检验设备id是否正确
        cJSON* id = cJSON_GetObjectItemCaseSensitive(frame, "device_id");
        if (!cJSON_IsString(id)) {
            printf("id is not a string!\r\n");
            cJSON_Delete(frame);
            return;
        }
        if (strcmp(id->valuestring, (const char *)device_id) == 0) {
            // 确保未结束才起作用
            if (ACK.end_flag != true) {
                IS_Updating = 1;    // 升级中
                // 提取新固件版本
                cJSON* version = cJSON_GetObjectItemCaseSensitive(frame, "version");
                if (!cJSON_IsString(version)) {
                    printf("version is not a string!\r\n");
                    cJSON_Delete(frame);
                    return;
                }

                static char v[15] = {0};
                strcpy(v, version->valuestring);
                printf("v: %s\r\n", v);
                FactoryInformation.current_fw = v;  // 更新设备固件版本号

                // 计算要传输的块数
                cJSON* file_size = cJSON_GetObjectItemCaseSensitive(frame, "file_size");
                cJSON* block_size = cJSON_GetObjectItemCaseSensitive(frame, "block_size");
                // 确保剩余空间足够, 假设足够
                if (1) {
                    FactoryInformation.fw_size = file_size->valueint;  // 更新设备固件大小
                    int block_num = (file_size->valueint + block_size->valueint - 1) / block_size->valueint;
                    printf("%d, %d, %d\r\n", file_size->valueint, block_size->valueint, block_num);

                    Data_Reception_param.current_blocks = 0;
                    Data_Reception_param.remaining_blocks = block_num;
                    Data_Reception_param.next_seq = 1;

                    ACK.device_id = (char*)device_id;
                    ACK.status = "ok";
                    ACK.next_seq = Data_Reception_param.next_seq;
                } else {
                    ACK.status = "Insufficient_space";
                    ACK.next_seq = 0;
                }
                // 设备应答应答ack
        //        {
        //          "type": "ack",
        //        "device_id": "DEVICE_123",
        //          "status": "ok",
        //          "next_seq": 1
        //        }
                ACK.end_flag = false;
                char* ack = DeviceAckBuid(ACK);
                SendData_To_CommunicationDev((void*)ack, strlen(ack));
                cJSON_free(ack);
            }
        }
    // 2）数据帧
    } else if (strcmp(type->valuestring, "data") == 0) {
        // 确保接收了起始信号或者数据帧没传输完才执行
        if (Data_Reception_param.remaining_blocks != 0) {
            cJSON* current_seq = cJSON_GetObjectItemCaseSensitive(frame, "seq");
            // 更新当前帧为 current_seq->valueint
            Data_Reception_param.current_blocks = current_seq->valueint;
            // 比较 先前的 next_seq ？= current_blocks
            if (Data_Reception_param.next_seq == Data_Reception_param.current_blocks) {
                cJSON* offset = cJSON_GetObjectItemCaseSensitive(frame, "offset");
                Data_Reception_param.offset = offset->valueint;
                cJSON* base64_data = cJSON_GetObjectItemCaseSensitive(frame, "data");
                Data_Reception_param.base64_data = base64_data->valuestring;
                cJSON* check_code = cJSON_GetObjectItemCaseSensitive(frame, "checksum");
                Data_Reception_param.check_code = check_code->valuestring;
                printf("check_code: %s\r\n", Data_Reception_param.check_code);

                // 解码base64
                static uint8_t buffer[400] = {0};
                unsigned int len = base64_decode(Data_Reception_param.base64_data,
                        strlen(Data_Reception_param.base64_data), buffer);
                // 校验
                uint8_t check_sum = calculate_sum_check(buffer, len);
                uint8_t checkCode = parse_checkCode(Data_Reception_param.check_code);
                printf("check code: %s, calculate_sum is: 0x%0X\r\n",
                        Data_Reception_param.check_code, check_sum);
                printf("check_sum - result = %u\r\n", check_sum - checkCode);
                if (check_sum == checkCode) {
                    // 计算写入地址  = 基地址 + 偏移量
                    Program_addr = FLASH_BaseAddr + Data_Reception_param.offset;
                    // 说明数据没问题
                    // 从设置的app地址写入flash
                    printf("decode and write...base64Data:%s, data: %s, len: %d, addr: 0x%08X, offset: %d\r\n",
                            Data_Reception_param.base64_data, buffer, len, Program_addr, Data_Reception_param.offset);

                    // 先解锁Flash
                    FLASH_Unlock_Fast();
                    // 擦除目标页
                    FLASH_ErasePage_Fast(Program_addr);
                    // 写入
                    CH32_IAP_Program(Program_addr, (u32*)buffer);
                    // 上锁
                    FLASH->CTLR |= ((uint32_t)0x00008000);
                    FLASH->CTLR |= ((uint32_t)0x00000080);

                    static u8 test_buf[100] = {0};
                    FLASH_Read(Program_addr, test_buf, len);
                    printf("read from flash: %s\r\n", buffer);

                    //更新接收参数与应答参数
                    Data_Reception_param.next_seq ++;
                    Data_Reception_param.remaining_blocks --;
                    // 若所剩块数为0， 则说明数据传输完成
                    if (Data_Reception_param.remaining_blocks == 0) {
                        ACK.next_seq = TransEndSeq;
                    } else {
                        ACK.next_seq = Data_Reception_param.next_seq;
                    }
                    ACK.status = "ok";
                } else {
                    ACK.status = "check_sum_err";
                }
                ACK.end_flag = false;
                // 发送应答
                char* ack = DeviceAckBuid(ACK);
                SendData_To_CommunicationDev((void*)ack, strlen(ack));
                cJSON_free(ack);
            }
        }
    // 3）结束帧
    } else if (strcmp(type->valuestring, "end") == 0) {
        /*
        {
          "type": "end",
        "device_id": "CH32_001",
          "received_frames": 1,
          "error_msg": ""
        }
         */
        // 检验设备id是否正确
        cJSON* id = cJSON_GetObjectItemCaseSensitive(frame, "device_id");
        if (!cJSON_IsString(id)) {
            printf("id is not a string!\r\n");
            cJSON_Delete(frame);
            return;
        }
        if (strcmp(id->valuestring, (const char *)device_id) == 0) {
            cJSON* received_frames = cJSON_GetObjectItemCaseSensitive(frame, "received_frames");
            // 确保数据传输完成才执行
            if (Data_Reception_param.current_blocks == received_frames->valueint
                && Data_Reception_param.remaining_blocks == 0) {
                printf("received finished, total block: %d\r\n", Data_Reception_param.current_blocks);
                cJSON* err_msg = cJSON_GetObjectItemCaseSensitive(frame, "error_msg");
                printf("err_msg: %s\r\n", err_msg->valuestring);
                // 返回响应
                ACK.end_flag = true;
                char* ack = DeviceAckBuid(ACK);
                SendData_To_CommunicationDev((void*)ack, strlen(ack));
                cJSON_free(ack);
                // 更新设备信息
                (void)FactoryInformationUpdate(FactoryInformation);
                // 停掉定时器
                Stop_Timer();
                OTA_END_FLAG = 1;
                IS_Updating = 0;
            }
        }
    } else if (strcmp(type->valuestring, "stop") == 0) {
        // 检验设备id是否正确
        cJSON* id = cJSON_GetObjectItemCaseSensitive(frame, "device_id");
        if (!cJSON_IsString(id)) {
            printf("id is not a string!\r\n");
            cJSON_Delete(frame);
            return;
        }
        ACK.end_flag = true;
        ACK.status = "stop";
        char* ack = DeviceAckBuid(ACK);
        SendData_To_CommunicationDev((void*)ack, strlen(ack));
        cJSON_free(ack);
        // 停掉定时器
        Stop_Timer();
        OTA_END_FLAG = 1;
        IS_Updating = 0;
    } else if (strcmp(type->valuestring, "uart") == 0) {
        Send_UpgradeRequest();
    }
    cJSON_Delete(frame);
}


void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void) {
    if (USART_GetITStatus(dev.UARTx, dev.USART_IT) != RESET)
    {
        // 收到数据先关闭定时器
        Stop_Timer();
        DMA_Cmd(dev_dma_rx.DMAx_Channely, DISABLE);

        CommunicationDev_Data_Perse();
        memset((void*)uart2_dma_rx_buffer, 0, DMA_RX_BUFFER_SIZE);

        DMA_SetCurrDataCounter(dev_dma_rx.DMAx_Channely, DMA_RX_BUFFER_SIZE);
        DMA_Cmd(dev_dma_rx.DMAx_Channely, ENABLE);


//        读SR+DR清除空闲中断标志
        (void)dev.UARTx->STATR;
        (void)dev.UARTx->DATAR;
////          下面方法也一样的
//        USART_ReceiveData(dev.UARTx);
//        USART_ClearFlag(dev.UARTx, USART_IT_IDLE);
    }
}



void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM2_IRQHandler(void) {
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {
        printf("TimeOut\r\n");
        if (IS_Updating == 0) {
            Send_UpgradeRequest();
        } else {
            // 再次发送需要服务器回应ack
            char* ack = DeviceAckBuid(ACK);
            SendData_To_CommunicationDev((void*)ack, strlen(ack));
            cJSON_free(ack);
        }
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}
